package com.blog.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.blog.constants.SystemConstants;
import com.blog.domain.DTO.AddArticleDto;
import com.blog.domain.DTO.ArticleListDto;
import com.blog.domain.ResponseResult;
import com.blog.domain.entity.*;
import com.blog.domain.vo.*;
import com.blog.mapper.ArticleMapper;
import com.blog.mapper.ArticleTagMapper;
import com.blog.service.*;
import com.blog.utils.BeanCopyUtils;
import com.blog.utils.RedisCache;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class ArticleServiceImpl extends ServiceImpl<ArticleMapper, Article> implements ArticleService {

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private ArticleTagService articleTagService;



	@Autowired
	private ArticleTagMapper articleTagMapper;
    /**热门文章查询
     *
     * @return
     */
    @Override
    public ResponseResult hotArticleList() {
        //查询热门文章并封装
        LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();
        //正式文章，0是正式文章
        queryWrapper.eq(Article::getStatus, SystemConstants.ARTICLE_STATUS_NORMAL);
        // 按照浏览量排序，
        queryWrapper.orderByDesc(Article::getViewCount);
        // 最多10条
        Page<Article> page = new Page<>(1,10);
        page(page,queryWrapper);

        List<Article> records = page.getRecords();

        /*List<HotArticleVo> hotArticleVo = new ArrayList<>();
        for (Article record : records) {
            HotArticleVo articleVo = new HotArticleVo();
            BeanUtils.copyProperties(record,articleVo);
            hotArticleVo.add(articleVo);
        }
*/
        List<HotArticleVo> hotArticleVos = BeanCopyUtils.copyBeanList(records, HotArticleVo.class);
        return ResponseResult.okResult(hotArticleVos);
    }
    /**分页查询文章列表
     *
     * @return
     */
	@Override
    public ResponseResult articleList(Integer pageNum, Integer pageSize, Long categoryId) {
        //查询条件
        LambdaQueryWrapper<Article> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        //如果有catyegoryid,则查询时要和传入的相同
        lambdaQueryWrapper.eq(Objects.nonNull(categoryId)&&categoryId>0,Article::getCategoryId,categoryId);
        //状态是发布的
        lambdaQueryWrapper.eq(Article::getStatus,SystemConstants.ARTICLE_STATUS_NORMAL);
        //对isTop降序
        lambdaQueryWrapper.orderByDesc(Article::getIsTop);
        //分页查询
        Page<Article> page = new Page<>(pageNum,pageSize);
        page(page,lambdaQueryWrapper);
        //查询categoryname
        List<Article> articles = page.getRecords();
        //根据categoryid查询name
	    articles.stream()
		         .map(article -> article.setCategoryName(
						 categoryService.getById(article.getCategoryId()).getName()))
		         .collect(Collectors.toList());
        //封装vo结果,此处是数据
        List<ArticleListVo> articleListVos = BeanCopyUtils.copyBeanList(articles, ArticleListVo.class);

        PageVo pageVo = new PageVo(articleListVos, page.getTotal());
        return ResponseResult.okResult(pageVo);


    }
    /**文章详情
     *
     */
	@Override
	public ResponseResult getArticleDetail(Long id) {
        //查询文章
        Article article = getById(id);
        //从redis中获取viewCount
        Integer viewCount = redisCache.getCacheMapValue(SystemConstants.REDIS_KEY, id.toString());
        article.setViewCount(viewCount.longValue());
        //转为Vo
        ArticleDetailVo articleDetailVo = BeanCopyUtils.copyBean(article, ArticleDetailVo.class);
        //根据分类id查询分类名
        Long categoryId = articleDetailVo.getCategoryId();
        Category category = categoryService.getById(categoryId);
        if (category!=null){
            articleDetailVo.setCategoryName(category.getName());
        }
        //封装响应返回
		return ResponseResult.okResult(articleDetailVo);
	}


    /**更新redis中的文章浏览量
     *
     * @param id
     * @return
     */
	@Override
	public ResponseResult updateViewCount(Long id) {
        //更新redis中对应id 的文章浏览量

        redisCache.incrementCacheMapValue("article:viewCount",id.toString(),1);

        return ResponseResult.okResult();

	}

    /**新增博文
     *
     * @param addArticleDto
     * @return
     */
	@Override
    @Transactional   //事物注解
	public ResponseResult addArticle(AddArticleDto addArticleDto) {
        //添加到博客表
        Article article = BeanCopyUtils.copyBean(addArticleDto, Article.class);
        save(article);

        /*List<ArticleTag> articleTags = addArticleDto.getTags()
                                         .stream()
                                                 .map(new Function<Long, ArticleTag>() {
                                                     @Override
                                                     public ArticleTag apply(Long tagId) {
                                                         return new ArticleTag(article.getId(),tagId);
                                                     }
                                                 }).collect(Collectors.toList());*/

        List<ArticleTag> articleTags = addArticleDto.getTags()
                .stream()
                .map(tagId -> new ArticleTag(article.getId(),tagId))
                .collect(Collectors.toList());


        //添加 博客和标签的关联关系表
        articleTagService.saveBatch(articleTags);

		return ResponseResult.okResult();
	}

	/**文章分页查询
	 *
	 * @param pageNum
	 * @param pageSize
	 * @param articleListDto
	 * @return
	 */
	@Override
	public ResponseResult listArticle(Integer pageNum, Integer pageSize,
	                                  ArticleListDto articleListDto) {
		//分页条件
		Page<Article> page = new Page<>();
		page.setCurrent(pageNum);
		page.setSize(pageSize);
		//查询条件
		LambdaQueryWrapper<Article> wrapper = new LambdaQueryWrapper<>();
		wrapper.like(StringUtils.hasText(articleListDto.getTitle()),Article::getTitle,articleListDto.getTitle());
		wrapper.like(StringUtils.hasText(articleListDto.getSummary()),Article::getSummary,articleListDto.getSummary());

		//分页

		page(page,wrapper);

		//封装数据，向前端返回结果
		PageVo pageVo = PageVo.builder()
				.rows(page.getRecords())
				.total(page.getTotal())
				.build();

		return ResponseResult.okResult(pageVo);


	}


	/**按文章id查询文章详情
	 *
	 * @param id
	 * @return
	 */
	@Override
	public ResponseResult<ArticleVo> selectArticleDatail(Long id) {
		//按id查询文章信息
		Article article = getById(id);
		ArticleVo articleVo = BeanCopyUtils.copyBean(article, ArticleVo.class);
		//查询文章对应的标签
		List<Long> list = articleTagService.selectTagByArticleId(id);
		articleVo.setTags(list);
		/*LambdaQueryWrapper<ArticleTag> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(ArticleTag::getArticleId,id);

		List<ArticleTag> tagIds = articleTagService.list(wrapper);

		List<Tag> lists = BeanCopyUtils.copyBeanList(tagIds, Tag.class);
		articleVo.setTags(lists);*/
		//封装Vo对象返回
		return ResponseResult.okResult(articleVo);

	}

	/**更新文章
	 *
	 * @param articleVo
	 * @return
	 */
	@Override
	@Transactional
	public ResponseResult updateArticle(ArticleVo articleVo) {
		//更新文章表
		Article article = BeanCopyUtils.copyBean(articleVo, Article.class);
		updateById(article);
		//更新文章标签表

		List<ArticleTag> articleTags = new ArrayList<>();

		for (Long tagId : articleVo.getTags()) {
			ArticleTag articleTag = new ArticleTag();
			//设置文章id
			articleTag.setArticleId(articleVo.getId());
			//设置标签id
			articleTag.setTagId(tagId);
			articleTags.add(articleTag);
		}
		//更新文章标签表时先删除原有的，再重新插入
		LambdaQueryWrapper<ArticleTag> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(ArticleTag::getArticleId,articleVo.getId());
		articleTagService.remove(wrapper);
		//重新插入
		articleTagService.saveBatch(articleTags);
		//articleTagMapper.updateBatchById(articleTags);

		return ResponseResult.okResult();
	}

	/**删除博客
	 *
	 * @param ids
	 * @return
	 */
	@Override
	public ResponseResult deleteArticle(List<Long> ids) {
		removeByIds(ids);
		return ResponseResult.okResult();
	}


}
